package BankerCalculate;

//银行家算法模拟
public class BankerCalculate {
    public static int[] p;//进程数量
    public static int[] Source;//系统各种资源的总量
    public static int[][] Max; // 最大需求矩阵
    public static int[][] Allocation;// 每个进程现在所分配的各种资源类型的实例数量
    public static int[] Available; // 可利用资源向量，即每种资源的现有实例数
    public static int[][] Need; // 每个进程还需要的剩余资源
    public static int[] Work; // 系统可供给进程的各类资源数量
    public static int[][] _Work;//存放每一次分配资源前的Work
    public static boolean[] Finish; // 标志一个进程是否可以得到其所需要是资源
    public static int[] Request; // 进程对每个资源的实例数的请求数量
    public static int flag = 0;
    BankerCalculate() {
        Source = new int[] { 10, 5, 7 };//资源总数定义
        Max = new int[][] {  //每个进程需要的资源定义
                { 7, 5, 3 },
                { 3, 2, 2 },
                { 9, 0, 2 },
                { 2, 2, 2 },
                { 4, 3, 3 } };
        Allocation = new int[][] { //给进程初始分配的资源
                { 0, 1, 0 },
                { 2, 0, 0 },
                { 3, 0, 2 },
                { 2, 1, 1 },
                { 0, 0, 2 } };
        Available = new int[Source.length];
        Need = new int[Max.length][Source.length];
        for (int m = 0; m < 3; m++)				//计算可分配资源（Available值）
            Available[m] = Source[m] - Allocation[0][m] - Allocation[1][m] - Allocation[2][m] - Allocation[3][m] - Allocation[4][m];
        for (int i = 0; i < 5; i++)              //计算need的值
            for (int j = 0; j < 3; j++)
                Need[i][j] = Max[i][j] - Allocation[i][j];
        p = new int[100];     //重获得资源数据
        Work = new int[100];
        _Work = new int[100][100];
        Request = new int[100];
        Finish = new boolean[100];
        BankerCalculate.Print(-1); //传递print方法，p值减一
    }
    public static void Print(int p) {  //输出资源分配的具体情况
        if (p == -1) {
            System.out.println("---------------------初始资源分配情况--------------------------");
            System.out.println("          Max        Allocation      Need        Available");
            System.out.println("       A   B   C     A   B   C     A   B   C     A   B   C");
            System.out.print("P[0]   ");
            for (int j = 0; j < 3; j++)
                System.out.print(Max[0][j] + "   ");
            System.out.print("  ");
            for (int j = 0; j < 3; j++)
                System.out.print(Allocation[0][j] + "   ");
            System.out.print("  ");
            for (int j = 0; j < 3; j++)
                System.out.print(Need[0][j] + "   ");
            System.out.print("  ");
            for (int j = 0; j < 3; j++)
                System.out.print(Available[j] + "   ");
            System.out.println();
            for (int i = 1; i < 5; i++) {
                printMembers(i, Max, Allocation, Need);
                System.out.println();
            }
        }else {
            if (flag == 0) {
                System.out.println("---------------------请求资源后分配情况--------------------------");
                System.out.println("         Work          Need       Allocation  Work+Allocation  Finish");
                System.out.println("       A   B   C     A   B   C     A   B   C     A   B   C");
                flag = 1;
            }
            if (flag == 1) {    //死锁或结束，资源分配情况
                printMembers(p, _Work, Need, Allocation);
                System.out.print("  ");
                for (int j = 0; j < 3; j++)
                    System.out.print((_Work[p][j]+Allocation[p][j]) + "   ");
                System.out.print("    "+Finish[p]);
                System.out.println();
            }
        }
    }

    private static void printMembers(int i, int[][] max, int[][] allocation, int[][] need) {
        System.out.print("P[" + i + "]   ");
        for (int j = 0; j < 3; j++)
            System.out.print(max[i][j] + "   ");
        System.out.print("  ");
        for (int j = 0; j < 3; j++)
            System.out.print(allocation[i][j] + "   ");
        System.out.print("  ");
        for (int j = 0; j < 3; j++)
            System.out.print(need[i][j] + "   ");
    }

    public boolean DeadlockCheck(int[][] a, int i, int[] b) {   //死锁检测
        int j;
        for (j = 0; j < Source.length; j++) {
            if (a[i][j] > b[j])
                return false;
        }
        return true;
    }
    public boolean SecurityCheck() {   //安全检查
        boolean run = true;
        int count = 0,procedure = 0;
        //对work进行初始化
        System.arraycopy(Available, 0, Work, 0, Source.length);
        for (int m = 0; m < Max.length; m++)//对finish进行初始化
            Finish[m] = false;
        while (run) {
            for (int i = 0; i < Max.length; i++) {
                count++;
                if (!Finish[i] && DeadlockCheck(Need, i, Work)) {
                    count--;
                    Finish[i] = true;
                    p[procedure] = i;
                    procedure++;
                    System.arraycopy(Work, 0, _Work[i], 0, Source.length);
                    for (int j = 0; j < Source.length; j++) {
                        Work[j] = Work[j] + Allocation[i][j];
                    }
                }
            }
            if(count==Max.length) {
                run=false;
            }
            else {
                run = true;
                count=0;
            }
        }
        for (int i = 0; i < Max.length; i++)
            if (!Finish[i]) {
                System.out.println("找不到一个安全序列,系统处于不安全状态。");
                return false;
            }
        System.out.println("存在一个安全序列，系统处于安全状态，可为其分配资源。");
        return true;
    }
    public void SourseRequest() {   //资源请求
        boolean run = true,run1 = true;
        while(run) {
            java.util.Scanner scanner = new java.util.Scanner(System.in);
            System.out.println("第几个进程需要请求资源？");
            int id = scanner.nextInt();
            if(id < 0 || id >= Max.length) {
                System.out.println("不存在此进程！请重新输入。");
            }else {
                while(run1) {
                    run = false;
                    int count = 0;
                    System.out.println("请依次输入此进程所请求的每类资源数：");
                    for(int i = 0; i < Source.length; i++) {
                        Request[i] = scanner.nextInt();
                    }
                    for(int i = 0; i < Source.length; i++) {
                        if(Request[i] > Need[id][i]) {
                            System.out.println("第"+(i+1)+"类资源请求量超出最大值！无效。");
                            count++;
                        }
                    }
                    if(count > 0)
                        run1 = true;
                    if(count == 0) {
                        run1 = false;
                        for (int k = 0; k < Source.length; k++) {
                            Available[k] = Available[k] - Request[k];
                            Allocation[id][k] = Allocation[id][k] + Request[k];
                            Need[id][k] = Need[id][k] - Request[k];
                        }
                    }
                }
            }
        }
    }
    public void Distribution() { //资源分配
        if(SecurityCheck())
            for(int i =0 ; i < Max.length;i++)
                BankerCalculate.Print(p[i]);
    }
}
